use super::error::AuthError;
use axum::{
    extract::{FromRequestParts, Request},
    middleware::Next,
    response::Response,
};
use http::{header, request::Parts, StatusCode};
use jsonwebtoken::{decode, errors::ErrorKind, DecodingKey, Validation};
use shq_common::prelude::Claims;
// 自定义扩展数据，将在中间件中添加
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct UserContext {
    pub user_id: u32,
}
// 实现 FromRequestParts 以便在 Server Function 中提取
#[async_trait::async_trait]
impl<S> FromRequestParts<S> for UserContext
where
    S: Send + Sync,
{
    type Rejection = StatusCode;

    async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
        parts
            .extensions
            .get::<UserContext>()
            .cloned()
            .ok_or(StatusCode::INTERNAL_SERVER_ERROR)
    }
}
// 添加Token验证中间件
pub async fn auth_middleware(mut req: Request, next: Next) -> Result<Response, AuthError> {
    let path = req.uri().path();
    if !path.starts_with("/api/protect") {
        // 如果是非保护请求，直接放行
        return Ok(next.run(req).await);
    }
    let user_id = get_user_id_by_req(&req);
    let response = match user_id {
        Ok(user_id) => {
             let context = UserContext { user_id };
             req.extensions_mut().insert(context);
             Ok(next.run(req).await)
        },
        Err(e) => {
            Err(e)
        }
    };
    response
}
pub fn get_user_id_by_req(req: &Request) -> Result<u32, AuthError> {
    let token = match req.headers().get(header::COOKIE) {
        Some(cookie_header) => cookie_header
            .to_str()
            .map_err(|_| AuthError::AuthenticationFailed),
        None => {
            log::error!("未找到Cookie头");
            Err(AuthError::AuthenticationFailed)
        }
    }
    .and_then(|cookie_str| {
        cookie_str
            .split(';')
            .find_map(|cookie| {
                let parts: Vec<&str> = cookie.trim().split('=').collect();
                if parts.len() == 2 && parts[0] == "auth_token" {
                    Some(parts[1].to_string())
                } else {
                    None
                }
            })
            .ok_or_else(|| {
                log::error!("未找到auth_token或格式错误");
                AuthError::AuthenticationFailed
            })
    });
    let token = match token {
        Ok(token) => token,
        Err(e) => {
            log::error!("未找到auth_token或格式错误: {}", e);
            return Err(AuthError::AuthenticationFailed);
        }
    };
    let jwt_config = &shq_common::prelude::get_app_config().jwt;
    let claims = decode::<Claims>(
        token.as_str(),
        &DecodingKey::from_secret(jwt_config.secret.as_bytes()),
        &Validation::default(),
    )
    .map_err(|e| match e.kind() {
        ErrorKind::ExpiredSignature => AuthError::TokenExpired,
        _ => AuthError::AuthenticationFailed,
    });
    let claims: Claims = match claims {
        Ok(c) => c.claims,
        Err(e) => {
            log::error!("Token验证失败: {}", e);
            return Err(AuthError::AuthenticationFailed);
        }
    };
    let user_id = claims.user_id;
    Ok(user_id)
}

// let mut menu_id: Option<u32> = None;
//     let parts: Vec<&str> = path.split('/').collect();
//     if let Some(mid_str) = parts.get(2) {
//         let mid: u32 = mid_str.parse().or_else(|_e| {
//             Err(AuthError::InternalServerError(format!(
//                 "解析路由中的menu_id参数失败:{mid_str}不是u32类型",
//             )))
//         })?;
//         menu_id = Some(mid);
//         if let Some(at_str) = parts.get(3) {
//             let at = AuthType::from_str(at_str).ok_or(AuthError::InternalServerError(format!(
//                 "解析路由中的auth_type参数失败:{at_str}有效的auth_type",
//             )))?;
//             let user_perm = shq_pas_backend::get_auth_type(user_id, mid)
//                 .await
//                 .map_err(|e| {
//                     AuthError::InternalServerError(format!(
//                         "验证用户权限时，执行get_auth_type出错:{}",
//                         e.to_string()
//                     ))
//                 })?
//                 .ok_or(AuthError::NotPermitted(at.clone()))?;
//             if !user_perm.auth_types.contains(&at) {
//                 return Err(AuthError::NotPermitted(at));
//             }
//         }
//     }
